package com.ndhutu.ee.util.pay.yfk;

import com.alibaba.fastjson.JSONObject;
import com.ndhutu.ee.util.pay.Notify;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 云支付工具类
 */
public class YFKPayUtil {
    private static Logger log = LoggerFactory.getLogger(YFKPayUtil.class);

    public static String stringToMD5(String plainText) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                    plainText.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有这个md5算法！");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }

    /**
     * 创建token
     * @param config
     * @return
     */
    private static String createToken(YFKPayConfig config){
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
        return stringToMD5(config.getAppSecret()+sdf.format(now) );
    }

    /**
     * 验证回调的token是否合法(5分钟误差)
     * @param config
     * @param token
     * @return
     */
    public static Boolean validateToken(YFKPayConfig config, String token) {
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
        Date afterDate = new Date(now .getTime() + 300000);
        Date beginDate = new Date(now .getTime() - 300000);
        token=token.toLowerCase();///回调参数token转换成小写

        return token.equals(stringToMD5(config.getAppSecret()+sdf.format(now) ).toLowerCase())
                || token.equals(stringToMD5(config.getAppSecret()+sdf.format(afterDate) ).toLowerCase())
                || token.equals(stringToMD5(config.getAppSecret()+sdf.format(beginDate) ).toLowerCase());
    }

    /**
     * 支付下单
     * @param config
     * @param orderNumber   订单号
     * @param amount    订单金额，单位分
     * @param body  商品描述
     * @return
     * @throws Exception
     */
    public static String order(YFKPayConfig config, String orderNumber, Integer amount, String body) throws Exception{
        String url = "http://pay.yunfukuan.net/Payment";

        Map<String, String> params = new HashMap<>();
        params.put("appkey", config.getAppKey());
        params.put("token", createToken(config));
        params.put("tradeName", body);
        params.put("amount", amount/100.0+"");
        params.put("userOrder", orderNumber);

        StringBuffer buff = new StringBuffer();
        for(Map.Entry<String, String> entry : params.entrySet()){
            buff.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "utf-8")).append("&");
        }
        String s = buff.substring(0, buff.length()-1);
        url += "?"+s;
        log.info("云支付下单地址："+url);

        return url;
    }

    /**
     * 获取回调请求参数
     * @param request
     * @return
     * @throws Exception
     */
    public static Map<String, String> getNotifyRequestParams(HttpServletRequest request) throws Exception{
        Map<String,String> params = new HashMap<String, String>();

        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        log.debug("云支付支付回调参数："+ JSONObject.toJSONString(params));

        return params;
    }

    /**
     * 校验回调请求
     * @param params    回调请求参数
     * @param config
     * @param notify
     * @return
     * @throws Exception
     */
    public static String verifyNotifyRequest(Map<String, String> params, YFKPayConfig config, Notify notify) throws Exception{
        //token验证
        boolean flag = validateToken(config, params.get("token"));

        if(flag){
            if("success".equals(params.get("status"))){
                String orderNumber = params.get("orderNo");
                Integer amount = (int)(Double.parseDouble(params.get("money")) * 100);

                //统一回调
                notify.handleNotify(orderNumber, amount);

                log.info("订单" + orderNumber + "云支付回调成功");
            }
            return "callbacksuccess";
        }

        return "callbackfail";
    }


    public static void main(String[] args) throws Exception{
        YFKPayConfig config = new YFKPayConfig() {
            @Override
            public String getAppKey() {
                return "9067066374";
            }

            @Override
            public String getAppSecret() {
                return "57d96552050a5b9efd19d2bfdd0428fb";
            }
        };
        System.out.println(createToken(config));
//        System.out.println(order(config, "TU22895567", 12, "iPhone"));

        boolean flag = validateToken(config, "e2ff69ba24adef38eb02c0b243abe694");
        System.out.println(flag);

//        System.out.println(MD5Util.encode32("1234567890abcdef2020061416"));
    }
}
